package core

import (
	"github.com/huandu/skiplist"
	"reflect"
)

type InitContainer[T any] struct {
	list *skiplist.SkipList
}

func NewInitContainer[T any]() *InitContainer[T] {
	return &InitContainer[T]{
		list: skiplist.New(skiplist.Int),
	}
}

func (c *InitContainer[T]) Iterator() <-chan T {
	ch := make(chan T)
	go func() {
		defer close(ch)
		for elem := c.list.Front(); elem != nil; elem = elem.Next() {
			if init, ok := elem.Value.(T); ok {
				ch <- init
			} else if inits, ok := elem.Value.([]T); ok {
				for _, init := range inits {
					ch <- init
				}
			} else {
				panic("unsupported type")
			}
		}
	}()
	return ch
}

func (c *InitContainer[T]) Register(key int, value T) {
	if val, ok := c.list.GetValue(key); ok {
		if inits, ok := val.([]T); ok {
			c.list.Set(key, append(inits, value))
		} else if init, ok := val.(T); ok {
			c.list.Set(key, []T{init, value})
		}
	} else {
		c.list.Set(key, value)
	}
}

func (c *InitContainer[T]) Unregister(key int, value T) {
	if val, ok := c.list.GetValue(key); ok {
		if inits, ok := val.([]T); ok {
			for i, init := range inits {
				if reflect.DeepEqual(init, value) {
					if len(inits) == 1 {
						c.list.Remove(key)
					} else {
						c.list.Set(key, append(inits[:i], inits[i+1:]...))
					}
					return
				}
			}
		} else if init, ok := val.(T); ok {
			if reflect.DeepEqual(init, value) {
				c.list.Remove(key)
			}
		}
	}
}
